A*及射線檢測運用-激光與子彈
A*及射線檢測運用-激光與子彈:
DEMO
github連結
(一) 概要
在開發這款遊戲前,我心想要製作一款射擊類遊戲,因此我研究了有關於射線的內容。此外,由於射擊類遊戲,我在地圖上新增了一些地形。因為這個原因,像是無限繼承中的簡單敵人AI就沒辦法做到追蹤玩家,而是會被地形卡住。所以,我搜尋了有關於敵人AI尋路的功能,最後決定使用A*來實作。
同樣的,為了使遊戲具有可玩性,我依舊添加了無限波數的系統。只是這次我想在強化方式上,做出一些改變,從隨機的強化,進入到有規則、有策略性的強化。以及加入更多RPG元素。
因此,我選擇了升級系統,透過擊敗敵人來獲得經驗值,從而升級。升級後,獲得技能點,進行天賦加點。透過這樣的方式來強化玩家。
不同於上一款遊戲的部分則是,我將Buff系統安裝到了敵人的身上,在每次敵人生成時,隨機給予特定數量的特定Buff,以此提升遊戲的隨機性,以及挑戰性。其中包含:普通武器免疫、能量武器免疫、巨大化等。
至於這款遊戲的核心,槍戰系統。我採用子彈數的方式來實現,總共有數種不同的槍可供使用,這些槍都有子彈數限制,子彈則可透過擊殺敵人隨機掉落。用意除了限制玩家的火力外,也是想使遊戲更有難度。可是不同於普通槍戰遊戲的點是,我添加了使用能量的武器,這種武器的能量用光後會自動回復。以及次元武器,這種武器消耗的是儲備的次數,但也會隨著時間回復。
(二) 遊戲玩法
透過WASD移動腳色,鼠標瞄準,鼠標左鍵射擊、鼠標右鍵手刀。並透過E、R、T、Y、G、H可進行武器切換,按下P鍵可暫停遊戲。
在天賦樹頁面,可以將現有天賦點進行分配,只是目前只有啟動武器的幾個天賦,以及一些強化而已。
敵人則有危險度分級,從低到高分別是:白、綠、藍、紅、金、黑,分別代表敵人身上持有的Buff數量,從零到五。
(三) 子彈功能實裝
在這款遊戲中,我實裝了無限繼承中提到的追蹤彈功能。此外,也設計了四種不同的槍械,透過調整子彈的發射時間,以及速度、顏色、傷害等,分成了四種:步槍、加特林(機槍)、散彈槍、狙擊槍。
以及作為次元武器的次元跳躍,只要鎖定某個定點後,便能在數秒後,出現在那個位置。可以透過連續使用,做到花式操作的感覺。只是因為這個功能而出現了能出現在牆中以及場地外的BUG。目前暫時未處理。
(圖二十五)遊戲畫面以及武器欄
實際的代碼部分,則可在底下的路徑中找到。
槍械設計相關代碼:
(Ray Game\Assets\Scripts\Weapon.cs)
(四) 射線檢測_激光
在開發之前,我便決定要學習的功能其實是射線檢測。不論是作為平台類遊戲中,玩家跳躍時是否落到地面的判斷,或是檢測玩家是否接觸到可拾取物體的判斷。都能用射線檢測完成。
透過教學影片,我簡單的了解了有關射線檢測的內容。在教學影片中,將射線檢測放置在怪物身上,並讓怪物在定點來回移動。因為我覺得這樣的話難度太低,所以改造了一下,將怪物的激光實時對準玩家的所在地,並讓怪物追蹤玩家。
(圖二十六)怪物激光效果
1. private void Detect()
2. {
3. RaycastHit2D hitInfo = Physics2D.Raycast(firePoint.position, target.position - this.transform.GetChild(0).position, maxDist); //獲取射線命中物
4.
5. if(hitInfo.collider != null && shoot == true) //開啟射擊模式,且目標不為空
6. {
7. if(hitInfo.collider.tag == "Wall")
8. {
9. //Debug.DrawLine(firePoint.position, hitInfo.point, Color.green);
10.
11. lineRenderer.SetPosition(1, hitInfo.point);
12. lineRenderer.colorGradient = greenColor;
13. }
14. if (hitInfo.collider.tag == "Player")
15. {
16. //Debug.DrawLine(firePoint.position, hitInfo.point, Color.red);
17.
18. lineRenderer.SetPosition(1, hitInfo.point);
19. lineRenderer.colorGradient = redColor;
20.
21. GameObject.Find("Player").SendMessage("Hurt"); //命中玩家
22. }
23.
24. //Instantiate(hitEffect, hitInfo.point, Quaternion.identity); //生成爆炸效果
25. lineRenderer.SetPosition(0, firePoint.position);
26. }
27. }
(圖二十七)射線檢測部分代碼(Ray Game\Assets\Scripts\FireElement.cs)
在完成怪物部分的激光後,我開始嘗試在玩家身上增加激光武器,但不知道為何,機光束總是不能鎖定在玩家和鼠標之間,有時會偏移,有時會隨機旋轉。當時,我查了許多教學,只能大概知道是座標(世界座標或本地座標)轉換之間的問題,卻沒辦法解決這個問題。最後只能放棄。
(五) 敵人AI升級_A*尋路
我這次將敵人的AI升級,其原因是場地上出現了障礙物,因此簡單的追蹤玩家無法成功。在查找一些資料後,我選擇使用A*提供的尋路功能,能透過簡單的設定,完成地圖的配置,使敵人依著設定,走在沒有障礙物的路上,並朝著玩家前進。
(圖二十八)A*底下的地圖設定
(六) 存檔機制
在無限繼承中提到過PlayerPrefs的儲存方式,但在這款遊戲中,我使用了其他的存檔方式。最一開始我嘗試著使用的是JSON的序列化方式,但因為存在BUG始終無法解決,我最終改用二進制的方式儲存。
從實作來看,二進制和JSON的實作較為相似,但XML有明顯的不同,至於PlayerPrefs則完全不一樣。值得一提的是,因為我的天賦樹是透過scriptableObject來儲存,因此當我想在遊戲中,儲存升級後的技能點,並在天賦樹介面同步時,會出現問題。在查詢完相關資料後,似乎是因為沒有激活的原因。於是在存檔機制上,我後來設計為不同的場景使用不同的存檔區塊。
在修正過程中,其實也有犯過蠢,比如說在數據改變時,重新儲存一次檔案。只是在那個時候,遊戲中的數據已經被初始化了,導致那份存檔除了修改過的數據外,其他全都是初始化的結果。當時卡了蠻久的。
存檔機制實作:
(Ray Game\Assets\Scripts\PlayerUI.cs)
(七) 天賦樹系統
最後,是這款遊戲的核心之一,天賦樹系統,主要的設計是根據教學影片得來的,從建立scriptableObject做到在Unity中便可以直接設計天賦,簡單化天賦的管理相當於將資料庫實體化。
如果在製作無限繼承時,我便知道這個功能的話,我應該不會在程式碼中建立資料庫,而是改用scriptableObject來做。過程的確是較輕鬆,不論是資料處理還是應用,都能透過圖形化來處理。唯一的問題就是在存檔機制中提到的,未激活導致兩個場景之中,無法直接調用變數。
天賦模板:
(Ray Game\Assets\Scripts\SkillData.cs)
天賦樹系統:
(Ray Game\Assets\Scripts\SkillManager.cs)
(圖二十九)天賦樹系統